package com.zhouyiquan.qqserver.service;

import com.zhouyiquan.qqcommon.Message;
import com.zhouyiquan.qqcommon.MessageType;
import com.zhouyiquan.qqcommon.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 周益全 (https://gitee.com/zfovikqdev928)
 * @BugFeedBackEmail: zfovikqdev928@126.com
 * @Date: Create in 2023-01
 * @Description: 服务端，监听 9999 端口，等待客户端的连接，并保持通信
 * @Version:
 */
public class QQServer {

    // 模拟数据库用户，也可以替换 HashMap（非线程安全） ,ConcurrentHashMap （线程安全）
    private static final ConcurrentHashMap<String, User> validUsers = new ConcurrentHashMap<>();

    // 静态块加载对象的时候，会初始化一次
    static {
        validUsers.put("100", new User("100", "123456"));
        validUsers.put("200", new User("200", "123456"));
        validUsers.put("300", new User("300", "123456"));
        validUsers.put("至尊宝", new User("至尊宝", "123456"));
        validUsers.put("紫霞仙子", new User("紫霞仙子", "123456"));
        validUsers.put("菩提老祖", new User("菩提老祖", "123456"));
    }

    private ServerSocket ss = null;

    public QQServer() {
        System.out.println("服务端在 9999 端口监听....");
        try {
            ss = new ServerSocket(9999);

            // 监听应该是循环状态
            // 因为当和某个客户端连接后，会继续监听，因此 while
            while (true) {
                Socket socket = ss.accept();    // 如果没有客户端连接，这里会造成阻塞
                // 读取客户端发送过来的数据
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());     // 输入流
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());  // 输出流
                User user = (User) ois.readObject();
                // 校验用户信息是否合法，后期可以接入数据库进行校验
                Message message = new Message();

                if (checkUser(user.getUserId(), user.getPasswd())) {
                    // 登录成功
                    message.setMessageType(MessageType.MESSAGE_LOGIN_SUCCEED);
                    oos.writeObject(message);

                    // 服务器端 创建一个线程 和 客户端保持通信，该线程需要持有 socket 对象
                    ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, user.getUserId());
                    serverConnectClientThread.start();

                    // 将该线程放入集合中管理
                    ManageServerConnectClientThread.addServerConnectClientThread(user.getUserId(), serverConnectClientThread);

                } else {
                    // 登录失败
                    System.out.println(user.getUserId() + "登陆失败");
                    message.setMessageType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                    socket.close();

                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 如果服务器退出了 while ，因此需要关闭资源
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new QQServer();
    }

    // 验证用户是否有效
    public boolean checkUser(String userId, String passwd) {
        User user = validUsers.get(userId);
        if (user == null) {
            return false;
        }
        return passwd.equals(user.getPasswd());
    }


}
